<script>
    /*
        问题：

            如何在 Visual Studio 中调试C#时查看内存的占用、以及内存中哪些类型对象占用内存比较多？
    */

    /*
        DeepSeek：

                在Visual Studio 中调试 C#时，查看内存占用和分析对象内存分布，有以下几种方：
    */

                /*
                    一、使用 "诊断工具" (Diagnostic Tools)

                            1、开启诊断工具

                                   <1>、方法1 ：【调试】---【窗口】---【显示诊断工具】

                                   <2>、方法2 ：【调试】---【选项】---【常规】---【启用诊断工具】

                            2、进行内存分析

                                        // 示例代码用于测试内存分析
                                        public class MemoryHeavyClass
                                        {
                                            private byte[] data = new byte[1024 * 1024]; // 1MB
                                            public string Name { get; set; }
                                        }

                                        public class LightClass
                                        {
                                            public int Id { get; set; }
                                            public string Description { get; set; }
                                        }

                                        class Program
                                        {
                                            static void Main()
                                            {
                                                var heavyList = new List<MemoryHeavyClass>();
                                                var lightList = new List<LightClass>();
                                                
                                                // 创建大量对象
                                                for (int i = 0; i < 1000; i++)
                                                {
                                                    heavyList.Add(new MemoryHeavyClass { Name = $"Heavy_{i}" });
                                                }
                                                
                                                for (int i = 0; i < 10000; i++)
                                                {
                                                    lightList.Add(new LightClass { Id = i, Description = $"Light_{i}" });
                                                }
                                                
                                                Console.ReadLine(); // 在此处设置断点分析内存
                                            }
                                        }
                */

                /*
                    二、内存快照分析

                            1、拍摄内存快照的步骤

                                      <1>、运行程序到端点

                                      <2>、在"诊断工具"窗口中点击 "拍摄快照"

                                      <3>、继续执行代码

                                      <4>、再次拍摄内存快照进行比较

                            2、分析快照内容
                                        
                                      <1>、对象数量：   每种类型的实力数量

                                      <2>、大小(size): 对象本身的大小

                                      <3>、包含的大小(Inclusive Size):  对象及其引用的所有对象的大小。
                */

                /*
                    三、使用即时窗口查看内存

                            在调试时使用即时窗口 (Immediate Window):

                                    // 查看特定类型的内存占用
                                    // 在即时窗口中输入：
                                    System.GC.GetTotaolMemory(true) // 强制GC后查看内存

                                    // 查看特定对象大小 (需要 Microsoft.Diagnostics.Runtime 扩展)
                                    // 或者使用 sizeof 运算符(仅对值类型有效)
                                    sizeof(int)  // 返回4
                */

                /*
                    四、性能探查器 (Performance Profiler)

                            1、使用内存使用率分析

                                    <1>、【调试】---【性能探查器】  或 【分析】---【性能探查器】

                                    <2>、选择 【内存使用率】

                                    <3>、点击 【开始】

                            2、分析结果包含：

                                    <1>、托管堆大小

                                    <2>、对象分配

                                    <3>、GC收集统计

                                    <4>、类型级别的内存分配
                */

                /*
                    五、使用 .NET 诊断工具 (dotnet-counters)

                                # 安装工具

                                dotnet tool install -g dotnet-counters

                                # 监控进程

                                dotnet-counters monitor --process-id [PID] --counters System.Runtime
                */

                /*
                    六、代码中监控内存

                                public static class MemoryMonitor
                                {
                                        public static void LogMemoryUsage(string stage)
                                        {
                                            long memory = GC.GetTotalMoemory(false);
                                            Console.WriteLine($"{stage}:{meemory/1024/1024} MB");

                                            // 获取各代GC统计
                                            for(int i=0;i<= GC.MaxGeneration;i++)
                                            {
                                                Console.WriteLine($"Gen {i} collection: {GC.CollectionCount(i)}");
                                            }
                                        }

                                        public static void ForceGCAndLog()
                                        {
                                            long before = GC.GetTotalMemory(true);
                                            GC.Collect();
                                            GC.WaiForPendingFinalizers();
                                            GC.Collect();
                                            long after = GC.GetTotalMemory(true);

                                            Console.WriteLine($"Memory after GC:{after / 1024 / 1024} MB");
                                            Console.WriteLine($"Freed: {(before -after) / 1024 / 1024} MB");
                                        }
                                }
                */

                /*
                    七、实用调试技巧

                               1、设置断点监控内存：
                               
                                       // 当内存超过特定阈值时中断
                                       if(GC.GetTotalMemory(false) > 100*1024*1024)  // 超过 100MB
                                       {
                                            System.Diagnostics.Debugger.Break();
                                       }

                               2、使用 MemoryFailPoint 预测内存分配：

                                        try
                                        {
                                            // 检查是否有足够内存分配 50MB
                                            using(new MemoryFailPoint(50))
                                            {
                                                // 执行内存密集型操作
                                                byte[] largeArray = new byte[50*1024*1024];
                                            }
                                        }
                                        catch(InsufficientMemoryException)  ★、Insufficient：  [翻译] 供应不足的
                                        {
                                            Console.WriteLine("内存不足，无法分配请求的大小");
                                        }
                */

                /*
                     八、最佳实践

                                1、在发布模式在分析：  发布模式的内存使用更接近实际情况。

                                2、多次采样：  在不同时间点拍摄多个内存快照进行比较。

                                3、关注大对象堆： 大于 85000字节的对象会进入大对象堆

                                4、检查内存泄漏： 比较操作前后的内存快照，识别未释放的对象

                                5、分析 Inclusive Size: 包含引用的总大小更能反应真实内存占用。


                            通过这些工具和方法，你可以有效地识别和解决 C#应用程序中的内存问题。
                */
</script>